<?php

/**
 * This is the model class for table "sd.categories".
 *
 * The followings are the available columns in table 'sd.categories':
 * @property string $id
 * @property string $relative_id
 * @property string $user_add
 * @property string $user_edit
 * @property string $title
 * @property string $alias
 * @property string $description
 * @property string $date_add
 * @property string $date_edit
 * @property integer $sort
 * @property integer $active
 * @property string $meta_keywords
 * @property string $meta_description
 * @property string $type
 * @property string $lang
 *
 * The followings are the available model relations:
 * @property Categories $parent
 * @property Categories[] $categories
 * @property CategoryDependencies[] $categoryDependencies
 * @property CategoryDependencies[] $categoryDependencies1
 * @property CategoryUrl[] $categoryUrls
 * @property Goods[] $goods
 */
class Categories extends CBaseActiveRecord
{

	public $childNodes = array();
	public $pages = array();

	/**
	 * @return string the associated database table name
	 */
	public function tableName()
	{
		return 'sd.categories';
	}

	/**
	 * @return array validation rules for model attributes.
	 */
	public function rules()
	{
		// NOTE: you should only define rules for those attributes that
		// will receive user inputs.
		return array(
			array('user_add, title, alias, date_add', 'required'),
			array('sort, active', 'numerical', 'integerOnly'=>true),
			array('relative_id, user_add, user_edit, page_id, parser_id', 'length', 'max'=>10),
			array('title, alias', 'length', 'max'=>100),
			array('meta_keywords, meta_description, store_url', 'length', 'max'=>255),
			array('type', 'length', 'max'=>45),
			array('description, date_edit', 'safe'),
			// The following rule is used by search().
			// @todo Please remove those attributes that should not be searched.
			array('id, relative_id, user_add, user_edit, title, alias, description, date_add, date_edit, sort, active, meta_keywords, meta_description, type, page_id, parser_id, store_url', 'safe', 'on'=>'search'),
		);
	}

	/**
	 * @return array relational rules.
	 */
	public function relations()
	{
		// NOTE: you may need to adjust the relation name and the related
		// class name for the relations automatically generated below.
		return array(
//			'categories' => array(self::HAS_MANY, 'Categories', 'parent_id'),
			'categoryDependencies' => array(self::HAS_MANY, 'CategoryDependencies', 'category_id'),
			'categoryDependencies1' => array(self::HAS_MANY, 'CategoryDependencies', 'dependence_id'),
			'categoryUrls' => array(self::HAS_MANY, 'CategoryUrl', 'category_id'),
			'goods' => array(self::HAS_MANY, 'Goods', 'category_id'),
		);
	}

	/**
	 * @return array customized attribute labels (name=>label)
	 */
	public function attributeLabels()
	{
		return array(
			'id' => 'ID',
			'relative_id' => 'Relative',
			'user_add' => 'User Add',
			'user_edit' => 'User Edit',
			'title' => 'Title',
			'alias' => 'Alias',
			'description' => 'Description',
			'date_add' => 'Date Add',
			'date_edit' => 'Date Edit',
			'sort' => 'Sort',
			'active' => 'Active',
			'meta_keywords' => 'Meta Keywords',
			'meta_description' => 'Meta Description',
			'type' => 'Type',
			'page_id' => 'page_id',
			'parser_id' => 'parser_id',
			'store_url' => 'store_url',
		);
	}

	/**
	 * Retrieves a list of models based on the current search/filter conditions.
	 *
	 * Typical usecase:
	 * - Initialize the model fields with values from filter form.
	 * - Execute this method to get CActiveDataProvider instance which will filter
	 * models according to data in model fields.
	 * - Pass data provider to CGridView, CListView or any similar widget.
	 *
	 * @return CActiveDataProvider the data provider that can return the models
	 * based on the search/filter conditions.
	 */
	public function search()
	{
		// @todo Please modify the following code to remove attributes that should not be searched.

		$criteria=new CDbCriteria;

		$criteria->compare('id',$this->id,true);
		$criteria->compare('relative_id',$this->relative_id,true);
		$criteria->compare('user_add',$this->user_add,true);
		$criteria->compare('user_edit',$this->user_edit,true);
		$criteria->compare('title',$this->title,true);
		$criteria->compare('alias',$this->alias,true);
		$criteria->compare('description',$this->description,true);
		$criteria->compare('date_add',$this->date_add,true);
		$criteria->compare('date_edit',$this->date_edit,true);
		$criteria->compare('sort',$this->sort);
		$criteria->compare('active',$this->active);
		$criteria->compare('meta_keywords',$this->meta_keywords,true);
		$criteria->compare('meta_description',$this->meta_description,true);
		$criteria->compare('type',$this->type,true);
		$criteria->compare('page_id',$this->page_id,true);
		$criteria->compare('parser_id',$this->parser_id,true);
		$criteria->compare('store_url',$this->store_url,true);

		return new CActiveDataProvider($this, array(
			'criteria'=>$criteria,
		));
	}

	/**
	 * Returns the static model of the specified AR class.
	 * Please note that you should have this exact method in all your CActiveRecord descendants!
	 * @param string $className active record class name.
	 * @return Categories the static model class
	 */
	public static function model($className=__CLASS__)
	{
		return parent::model($className);
	}

	public function createUrlId()
	{
		return $this->alias;
	}

	public function onlyPublic($onlyPublic = true)
	{
		if($onlyPublic === true)
			$this->dbCriteria->addColumnCondition(array(
			                                           'active' => '1'
			                                      ));

		return $this;
	}

	public function getAll($withoutId = null, $onlyActive = false, $withoutRoot = false, $type = null)
	{
		$criteria = $this->getDbCriteria();
//		$criteria->addCondition('active = 1');

		if($onlyActive)
			$criteria->addColumnCondition(array('active' => 1));

		if($type !== null)
			$criteria->addColumnCondition(array('type' => $type));

		if($withoutRoot)
			$criteria->addNotInCondition('relative_id', array('null'));

		if($withoutId > 0)
		{
			$criteria->addNotInCondition('id', (array)$withoutId);
		}

		$oRowset = $this->findAll($criteria);

		$oRowset = $this->toTree($oRowset, 'id', 'relative_id');

		return $oRowset;
	}

	public function saveRow($row)
	{
		if(!empty($row['category_id']))
        {
	        $row['relative_id'] = $row['category_id'];
            unset($row['category_id']);
        }
//		print_r($row); exit;

		$aRow = $row;
		$oRow = array();

		$id = 0;
		if(!empty($aRow['id']) && $aRow['id'] > 0)
		{
			$id = $aRow['id'];
			unset($aRow['id']);
		}

		if($id > 0)
			$oRow = $this->id($id)->find();

		if($oRow && $oRow->id > 0)
		{
			$aRow['date_edit'] = date('Y-m-d H:i:s');
			$aRow['user_edit'] = $aRow['user_id'];
		}

		if(!$oRow)
		{
			$oRow = new self;

			$aRow['date_add']  = date('Y-m-d H:i:s');
			$aRow['user_add']  = $aRow['user_id'];
		}

		if(!empty($aRow['title']))
			$aRow['alias'] = $this->createAlias($aRow['title']);

		if(empty($aRow['relative_id']))
			$aRow['relative_id'] = 0;

		$aRow['page_id'] = !empty($aRow['page_id']) ? $aRow['page_id'] : null;

		$oRow->setAttributes($aRow);

		$oRow->save();

		if($oRow->id && $oRow->relative_id);
			$this->_addDependencies($oRow->id, $oRow->relative_id);

		return $oRow;
	}

	protected function _addDependencies($id, $relativeId)
	{
		if($relativeId < 1 || $id < 1)
			return false;

		$oDependency = new CategoryDependencies();
		$oDependency->deleteAll('dependence_id = '. $id);

		do
		{
			if($relativeId < 1)
				break;

			$oRow = array();
			$oRow = $this->id($relativeId)->find();

			if(!$oRow)
				break;

			$oDependency = new CategoryDependencies();
			$oDependency->attributes = array(
				'category_id' => $oRow->id, // Батьківська категорія
				'dependence_id' => $id, // Категорія дочірня
			);
			$oDependency->save(true);

			$relativeId = $oRow->relative_id;
		}
		while(true);

		return true;
	}

	public function getAllChild($categoryId)
	{
		$oDependency = new CategoryDependencies();
		$oCriteria = $oDependency->getDbCriteria();

		$oCriteria->select = 'dependence_id';
		$oCriteria->group = 'dependence_id';
		$oCriteria->addInCondition('category_id', (array)$categoryId);

		$result = $oDependency->findAll($oCriteria);

		$return = array();
		foreach($result as $row)
		{
			$return[$row['dependence_id']] = $row['dependence_id'];
		}

//		$return[$categoryId] = $categoryId;

//        print_r($return); exit;

		return $return;
	}

	public function getAllParents($categoryId)
	{
		$oDependency = new CategoryDependencies();
		$oCriteria = $oDependency->getDbCriteria();

		$oCriteria->select = 'category_id';
		$oCriteria->group = 'category_id';
		$oCriteria->addInCondition('dependence_id', (array)$categoryId);

		$result = $oDependency->findAll($oCriteria);

		$return = array();
		foreach($result as $row)
		{
			$return[$row['category_id']] = $row['category_id'];
		}

		return $return;
	}

	public function getUsedCategories($ids = array())
	{
//		$s = microtime(true);
		$oSphinx = new SphinxClient();
		$oSphinx->SetArrayResult(false);
		$oSphinx->SetRankingMode(SPH_RANK_NONE);

		if($ids)
			$oSphinx->SetFilter('category_id', (array)$ids);

		$aRes = $oSphinx->Query('', 'goods_categories');

		$aCatIds = array();
		if(!empty($aRes) && !empty($aRes['matches']))
			$aCatIds = array_keys($aRes['matches']);

		if(!$aCatIds)
			return array();

		$oRowset = $this->findAllByAttributes(array(), 'id IN('. implode(', ', (array)$aCatIds) .')');

//		echo microtime(true) - $s;

		return $oRowset;
	}


}
